package tiny

import (
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"
)

// 路由列表
var routeList map[string]func(http.ResponseWriter, *http.Request)

var httpMutex *http.ServeMux

// 默认文档
var indexFile string

// MIME 映射
var mimeTypes = map[string]string{
	"js": "application/x-javascript",
	"css": "text/css",
	"jpg": "image/jpeg",
	"jpeg": "image/jpeg",
	"html": "text/html",
	"png": "image/png",
	"json": "application/json",
	"xml": "text/xml",
	"ico": "image/x-icon",
}

// 初始化函数
func init()  {
	routeList = make(map[string]func(w http.ResponseWriter, r *http.Request))
	httpMutex = &http.ServeMux{}
	httpMutex.Handle("/", &indexHandle{})
}

type indexHandle struct {}

var wg = sync.WaitGroup{}

// 实现路由转发
func (h *indexHandle) ServeHTTP(w http.ResponseWriter, r *http.Request)  {

	reqUrl := r.URL.String()

	go func() {
		defer wg.Done()
		if h, ok := routeList[reqUrl]; ok {
			h(w, r)
			return
		}
		max := 0
		var callFunc func(w http.ResponseWriter, r *http.Request)
		for k, v := range routeList{
			if strings.HasPrefix(reqUrl, k) && len(k) > max {
				max = len(k)
				callFunc = v
			}
		}
		if callFunc != nil {
			callFunc(w, r)
			return
		}
		http.NotFound(w, r)
	}()
	wg.Add(1)
	wg.Wait()
}

// 创建路由
func Route(url string, callback func(w http.ResponseWriter, r *http.Request))  {
	routeList[url] = callback
}

// 静态文件服务
func Static(path string, url string)  {

	if !strings.HasSuffix(path ,"/"){
		path = path + "/"
	}

	pwd, err := os.Getwd()

	checkErr(err)

	routeList[url] = func(w http.ResponseWriter, r *http.Request) {
		subUrl := r.URL.String()[len(url):]
		if subUrl == "" {
			subUrl = indexFile
		}

		// 获取 MIME 类型
		mimeType := "text/plain"
		suffix := strings.Split(subUrl, ".")
		if len(suffix) != 0 {
			if res, ok := mimeTypes[strings.ToLower(suffix[len(suffix)-1])]; ok {
				mimeType = res
			}
		}
		fileName := pwd + path + subUrl
		stat, err := os.Stat(fileName)
		if err != nil {
			http.NotFound(w,r)
			return
		}
		if stat.IsDir() {
			http.NotFound(w, r)
			return
		}
		file, err := os.Open(fileName)
		if err != nil {
			w.WriteHeader(500)
			return
		}
		defer func() {
			err := file.Close()
			checkErr(err)
		}()
		res , err := ioutil.ReadAll(file)
		if err != nil {
			w.WriteHeader(500)
			return
		}

		// 设置响应头
		l, _ := time.LoadLocation("Asia/Shanghai")
		w.Header().Set("Content-Type", mimeType)
		w.Header().Set("Server", "Tiny_GO")
		w.Header().Set("Date", time.Now().In(l).Format("Mon, 10 Jun 2019 03:27:42 GMT"))
		w.Header().Set("Content-Length", strconv.Itoa(int(stat.Size())))
		if mimeType != "text/html" {
			w.Header().Set("Last-Modified", stat.ModTime().In(l).Format("Mon, 10 Jun 2019 03:27:42 GMT"))
			expires := time.Now().In(l).AddDate(0,0,7)
			w.Header().Set("Expires", expires.Format("Mon, 10 Jun 2019 03:27:42 GMT"))
			w.Header().Set("Max-Age", "604800")
			w.Header().Set("Cache-Control", "max-age=604800")
		}
		_, err = w.Write(res)
		if err != nil {
			w.WriteHeader(500)
			return
		}
	}
}

// 默认首页文档
func Index(fileName string)  {
	indexFile = fileName
}

// 检查错误
func checkErr(err error)  {
	if err != nil {
		panic(err)
	}
}

// 启动服务
func Run(addr string)  {
	log.Fatal(http.ListenAndServe(addr, httpMutex))
}
